﻿// Decompiled with JetBrains decompiler
// Type: TaleWorlds.CampaignSystem.TournamentGames.TournamentManager
// Assembly: TaleWorlds.CampaignSystem, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E85F8C15-4DF6-4E9C-A58A-29177E40D07A
// Assembly location: D:\steam\steamapps\common\Mount & Blade II Bannerlord\bin\Win64_Shipping_Client\TaleWorlds.CampaignSystem.dll

using System;
using System.Collections.Generic;
using System.Linq;
using TaleWorlds.CampaignSystem.Actions;
using TaleWorlds.CampaignSystem.Party;
using TaleWorlds.CampaignSystem.Settlements;
using TaleWorlds.Core;
using TaleWorlds.Library;
using TaleWorlds.SaveSystem;

#nullable disable
namespace TaleWorlds.CampaignSystem.TournamentGames
{
  public class TournamentManager : ITournamentManager
  {
    [SaveableField(1)]
    private List<TournamentGame> _activeTournaments;
    [SaveableField(4)]
    private readonly Dictionary<Hero, int> _worldWideTournamentLeaderboard;

    internal static void AutoGeneratedStaticCollectObjectsTournamentManager(
      object o,
      List<object> collectedObjects)
    {
      ((TournamentManager) o).AutoGeneratedInstanceCollectObjects(collectedObjects);
    }

    protected virtual void AutoGeneratedInstanceCollectObjects(List<object> collectedObjects)
    {
      collectedObjects.Add((object) this._activeTournaments);
      collectedObjects.Add((object) this._worldWideTournamentLeaderboard);
    }

    internal static object AutoGeneratedGetMemberValue_activeTournaments(object o)
    {
      return (object) ((TournamentManager) o)._activeTournaments;
    }

    internal static object AutoGeneratedGetMemberValue_worldWideTournamentLeaderboard(object o)
    {
      return (object) ((TournamentManager) o)._worldWideTournamentLeaderboard;
    }

    public TournamentManager()
    {
      this._worldWideTournamentLeaderboard = new Dictionary<Hero, int>();
      this._activeTournaments = new List<TournamentGame>();
    }

    public void AddTournament(TournamentGame game)
    {
      this._activeTournaments.Add(game);
      CampaignEventDispatcher.Instance.OnTournamentStarted(game.Town);
    }

    public void RemoveTournament(TournamentGame game) => this._activeTournaments.Remove(game);

    public TournamentGame GetTournamentGame(Town town)
    {
      return this._activeTournaments.Find((Predicate<TournamentGame>) (x => x != null && x.Town == town));
    }

    public void OnPlayerJoinMatch(Type gameType)
    {
    }

    public void OnPlayerJoinTournament(Type gameType, Settlement settlement)
    {
      CampaignEventDispatcher.Instance.OnPlayerJoinedTournament(settlement.Town, true);
      this._activeTournaments.Remove(this.GetTournamentGame(settlement.Town));
    }

    public void OnPlayerWatchTournament(Type gameType, Settlement settlement)
    {
      CampaignEventDispatcher.Instance.OnPlayerJoinedTournament(settlement.Town, false);
      this._activeTournaments.Remove(this.GetTournamentGame(settlement.Town));
    }

    public void OnPlayerWinMatch(Type gameType)
    {
    }

    public void OnPlayerWinTournament(Type gameType)
    {
    }

    public List<KeyValuePair<Hero, int>> GetLeaderboard()
    {
      return this._worldWideTournamentLeaderboard.OrderByDescending<KeyValuePair<Hero, int>, int>((Func<KeyValuePair<Hero, int>, int>) (pair => pair.Value)).ToList<KeyValuePair<Hero, int>>();
    }

    public int GetLeaderBoardRank(Hero hero)
    {
      return this.GetLeaderboard().FindIndex((Predicate<KeyValuePair<Hero, int>>) (kvp => kvp.Key == hero)) + 1;
    }

    public Hero GetLeaderBoardLeader()
    {
      Dictionary<Hero, int> tournamentLeaderboard = this._worldWideTournamentLeaderboard;
      Hero leaderBoardLeader = (Hero) null;
      int num1 = -1;
      foreach (Hero key in tournamentLeaderboard.Keys)
      {
        int num2 = tournamentLeaderboard[key];
        if (num2 > num1)
        {
          num1 = num2;
          leaderBoardLeader = key;
        }
      }
      return leaderBoardLeader;
    }

    public void InitializeLeaderboardEntry(Hero hero, int initialVictories = 0)
    {
      this._worldWideTournamentLeaderboard[hero] = initialVictories;
    }

    public void AddLeaderboardEntry(Hero hero)
    {
      int num;
      this._worldWideTournamentLeaderboard.TryGetValue(hero, out num);
      this._worldWideTournamentLeaderboard[hero] = num + 1;
    }

    public void DeleteLeaderboardEntry(Hero hero)
    {
      if (!this._worldWideTournamentLeaderboard.ContainsKey(hero))
        return;
      this._worldWideTournamentLeaderboard.Remove(hero);
    }

    public void ResolveTournament(TournamentGame tournament, Town town)
    {
      if (!town.IsUnderSiege)
      {
        MBList<CharacterObject> participantCharacters = tournament.GetParticipantCharacters(tournament.Town.Settlement, false);
        CharacterObject winner;
        this.SimulateTournament(participantCharacters, tournament.Town, out winner);
        if (winner.IsHero)
        {
          this.AddLeaderboardEntry(winner.HeroObject);
          this.GivePrizeToWinner(tournament, winner.HeroObject, false);
        }
        CampaignEventDispatcher.Instance.OnTournamentFinished(winner, (MBReadOnlyList<CharacterObject>) participantCharacters, tournament.Town, tournament.Prize);
      }
      else
        CampaignEventDispatcher.Instance.OnTournamentCancelled(town);
      this.RemoveTournament(tournament);
    }

    private void SimulateTournament(
      MBList<CharacterObject> participants,
      Town town,
      out CharacterObject winner)
    {
      float num1 = -1f;
      winner = (CharacterObject) null;
      foreach (CharacterObject participant in (List<CharacterObject>) participants)
      {
        if (participant.IsHero)
        {
          (SkillObject skill, int num2) = Campaign.Current.Models.TournamentModel.GetSkillXpGainFromTournament(town);
          participant.HeroObject.HeroDeveloper.AddSkillXp(skill, (float) num2);
        }
        float num3 = Campaign.Current.Models.TournamentModel.GetTournamentSimulationScore(participant) * (float) (0.75 + 0.25 * (double) MBRandom.RandomFloat);
        if ((double) num3 > (double) num1)
        {
          winner = participant;
          num1 = num3;
        }
      }
    }

    public void GivePrizeToWinner(
      TournamentGame tournament,
      Hero winner,
      bool isPlayerParticipated)
    {
      if (!isPlayerParticipated)
        tournament.UpdateTournamentPrize(isPlayerParticipated);
      if (winner.PartyBelongedTo == MobileParty.MainParty)
      {
        winner.PartyBelongedTo.ItemRoster.AddToCounts(tournament.Prize, 1);
      }
      else
      {
        if (winner.Clan == null)
          return;
        GiveGoldAction.ApplyBetweenCharacters((Hero) null, winner.Clan.Leader, tournament.Town.MarketData.GetPrice(tournament.Prize));
      }
    }
  }
}
